package com.xayy.mgt.service.impl;

import cn.kawins.base.result.CheckResult;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.TreeUtil;
import cn.kawins.mybatis.base.BaseServiceImpl;
import com.xayy.mgt.model.EquipTreeInfo;
import com.xayy.mgt.model.NodeTreeInfo;
import com.xayy.mgt.model.vo.NodeTreeInfoVo;
import com.xayy.mgt.service.EquipTreeService;
import com.xayy.mgt.service.NodeInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author plq
 */
@Service
public class EquipTreeServiceImpl extends BaseServiceImpl<EquipTreeInfo> implements EquipTreeService {

    @Autowired
    private NodeInfoService nodeInfoService;

    @Override
    public CheckResult<Object> getEquipTree() {
        List<EquipTreeInfo> equipTreeInfos = selectAll();
        if (CollUtil.isEmpty(equipTreeInfos)) {
            return CheckResult.fail("卫星列表信息为空");
        }
        List<NodeTreeInfoVo> treeInfoVos =
            equipTreeInfos.stream().map(x -> BeanUtil.copyBean(x, NodeTreeInfoVo.class)).collect(Collectors.toList());
        List<NodeTreeInfoVo> tree = TreeUtil.toTree(0L, treeInfoVos);
        return CheckResult.success(tree);
    }


    @Override
    public CheckResult<Object> getEquipNodeTreeForNumber(Integer number) {
        List<EquipTreeInfo> equipTreeInfos = selectAll();
        List<NodeTreeInfoVo> treeInfoVos = equipTreeInfos.stream().map(x -> BeanUtil.copyBean(x, NodeTreeInfoVo.class)).collect(Collectors.toList());
        List<NodeTreeInfoVo> tree = TreeUtil.toTree(0L, treeInfoVos);
        for(int i = 0 ; i < number ; i++){
            removeChild(tree);
            setEmptyChildIsNull(tree);
        }
        return CheckResult.success(tree);
    }

    /**
     * 设置空子节点为null
     */
    private void setEmptyChildIsNull(List<NodeTreeInfoVo> tree) {
        if(tree != null){
            for (NodeTreeInfoVo nodeTreeInfoVo : tree) {
                if(nodeTreeInfoVo.getChildList()!= null && nodeTreeInfoVo.getChildList().isEmpty()){
                    nodeTreeInfoVo.setChildList(null);
                }else{
                    setEmptyChildIsNull(nodeTreeInfoVo.getChildList());
                }
            }
        }
    }
    /**
     * 移除最后一级节点
     */
    private void removeChild(List<NodeTreeInfoVo> tree) {
        if(tree != null){
            for (NodeTreeInfoVo nodeTreeInfoVo : tree) {
                if(nodeTreeInfoVo.getChildList()!= null){
                    List<NodeTreeInfoVo> remove = new ArrayList<>();
                    for(NodeTreeInfoVo child:nodeTreeInfoVo.getChildList() ){
                        if(child.getChildList() != null){
                            removeChild(nodeTreeInfoVo.getChildList());
                        }else{
                            remove.add(child);
                        }
                    }
                    /*置为空，如果置为null则上级会被下次循环移除*/
                    nodeTreeInfoVo.getChildList().removeAll(remove);
                }
            }
        }
    }

    @Override
    public CheckResult<Object> addOrUpdate(EquipTreeInfo equipTreeInfo) {
        if (equipTreeInfo.getId() == null) {
            insert(equipTreeInfo);
        } else {
            CheckResult<String> checkName = checkName(true, equipTreeInfo);
            if (checkName.no()) {
                return CheckResult.fail(checkName.getCheckMsg());
            }
            updateByIdSelective(equipTreeInfo);
        }
        return CheckResult.success();
    }

    @Override
    public CheckResult<Object> deleteTreeById(Long id) {
        /*查询节点是否存在子节点，存在则不允许删除*/
        int count = selectCount(EquipTreeInfo.builder().parentId(id).build());
        if (count > 0) {
            return CheckResult.fail("该节点存在子节点，不允许删除，如需删除请先删除子节点。");
        }
        int result = deleteById(id);
        if (result > 0) {
            return CheckResult.success("删除成功");
        }
        return CheckResult.fail("删除失败");
    }

    @Override
    public CheckResult<Object> getTreeById(Long id) {
        EquipTreeInfo equipTreeInfo = selectById(id);
        return CheckResult.success(equipTreeInfo);
    }

    @Override
    public CheckResult<Object> getEquipNodeTree() {
        List<EquipTreeInfo> equipTreeInfos = selectAll();
        if (CollUtil.isEmpty(equipTreeInfos)) {
            return CheckResult.fail("卫星列表信息为空");
        }
        List<NodeTreeInfoVo> treeInfoVos =
                equipTreeInfos.stream().map(x -> BeanUtil.copyBean(x, NodeTreeInfoVo.class)).collect(Collectors.toList());
        // 查询卫星节点
        List<NodeTreeInfo> nodeTreeInfos = nodeInfoService.select(NodeTreeInfo.builder().level(0).build());
        List<NodeTreeInfoVo> treeInfoVos1 = nodeTreeInfos.stream().map(x -> BeanUtil.copyBean(x, NodeTreeInfoVo.class)).collect(Collectors.toList());
        treeInfoVos.addAll(treeInfoVos1);
        List<NodeTreeInfoVo> tree = TreeUtil.toTree(0L, treeInfoVos);
        return CheckResult.success(tree);
    }




    /**
     * 名称重复校验
     *
     * @param isUpdate
     *            是否更新
     * @param equipTreeInfo
     *            入参
     * @return 结果日志
     */
    private CheckResult<String> checkName(Boolean isUpdate, EquipTreeInfo equipTreeInfo) {
        Example example = new Example(EquipTreeInfo.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("nodeName", equipTreeInfo.getNodeName());
        criteria.andEqualTo("parentId", equipTreeInfo.getParentId());
        if (Boolean.TRUE.equals(isUpdate)) {
            criteria.andNotEqualTo("id", equipTreeInfo.getId());
        }
        List<EquipTreeInfo> equipTreeInfos = selectByExample(example);
        if (CollUtil.isNotEmpty(equipTreeInfos)) {
            return CheckResult.fail("节点名称：" + equipTreeInfo.getNodeName() + ",已存在");
        }
        return CheckResult.success();
    }

    /**
     * 新增节点设置节点层级卫星节点为0
     *
     * @param equipTreeInfo
     *            入参
     * @return 层级
     */
    private Integer setLevel(EquipTreeInfo equipTreeInfo) {
        EquipTreeInfo parent = selectById(equipTreeInfo.getParentId());
        if (BeanUtil.isNotEmpty(parent)) {
            return parent.getLevel() + 1;
        }
        return 0;
    }
}
